using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Net;
using Microsoft.Win32;
using System.Xml;
using System.Reflection;
using System.Diagnostics;

namespace SPALM.SharePointSoftwareFactory.SetupHelper
{
  public partial class ComponentDownload : UserControl
  {
    private string downloadDir = "";
    private string title = "";
    private string description = "";
    private string publisher = "";
    private string downloadUrl = "";
    private string pageUrl = "";
    private ComponentContainer parent = null;
    private string productGuid = "";
    private string regKey = "";
    private bool isInstalled = false;
    private string downloadFilename = "";
    private string downloadSize = "";
    private bool displayInstallationStatus = true;
    private string vsVersion = "";
    private string checkFileExists = "";

    private string localExistingSetupFile = "";

    public ComponentDownload(ComponentContainer _parent, string _downloadDir, XmlNode node)
    {
      InitializeComponent();

      parent = _parent;
      downloadDir = _downloadDir;

      title = GetChildNode(node, "Title");
      description = GetChildNode(node, "Description");
      publisher = GetChildNode(node, "Publisher");
      downloadUrl = GetChildNode(node, "DownloadUrl");
      pageUrl = GetChildNode(node, "PageUrl");
      productGuid = GetChildNode(node, "ProductGuid");
      regKey = GetChildNode(node, "CheckRegKey");
      checkFileExists = GetChildNode(node, "CheckFileExists");
      downloadFilename = GetChildNode(node, "DownloadFilename");
      downloadSize = GetChildNode(node, "DownloadSize");
      try
      {
        displayInstallationStatus = Boolean.Parse(GetChildNode(node, "DisplayInstallationStatus"));
      }
      catch { }
      vsVersion = GetChildNode(node, "VSVersion");

      labelDescription.Text = description;
      labelTitle.Text = title;
      labelSize.Text = downloadSize;
      labelPublisher.Text = publisher;

      if (displayInstallationStatus)
      {
        this.pictureBox1.Visible = true;
      }
      else
      {
        this.pictureBox1.Visible = false;
      }

      if (string.IsNullOrEmpty(pageUrl))
      {
        buttonOpenPage.Visible = false;
      }

      //check if file exists in the current folder
      localExistingSetupFile = "";
      DirectoryInfo binDebugFolder = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
      foreach(FileInfo setupFile in binDebugFolder.GetFiles(downloadFilename, SearchOption.AllDirectories))
      {
        if (File.Exists(setupFile.FullName))
        {
          localExistingSetupFile = setupFile.FullName;
          button_install.Visible = true;
        }
      }  

      CheckInstallation();
    }

    private string GetChildNode(XmlNode node, string nodeName)
    {
      try
      {
        return node.SelectSingleNode(nodeName).InnerText;
      }
      catch { }
      return "";
    }

    private void buttonDownload_Click(object sender, EventArgs e)
    {
      panelDefault.Visible = false;
      parent.DownloadingInProgress(this);

      StartDownload();
    }

    private void StartDownload()
    {
      backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {

      string sUrlToReadFileFrom = downloadUrl;
      string sFilePathToWriteFileTo = Path.Combine(downloadDir, downloadFilename);

      Uri url = new Uri(sUrlToReadFileFrom);
      System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
      System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();

      try
      {
        response.Close();

        Int64 iSize = response.ContentLength;
        Int64 iRunningByteTotal = 0;
        using (System.Net.WebClient client = new System.Net.WebClient())
        {
          using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
          {
            using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
            {
              int iByteSize = 0;
              byte[] byteBuffer = new byte[iSize];
              while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
              {
                streamLocal.Write(byteBuffer, 0, iByteSize);
                iRunningByteTotal += iByteSize;

                double dIndex = (double)(iRunningByteTotal);
                double dTotal = (double)byteBuffer.Length;
                double dProgressPercentage = (dIndex / dTotal);
                int iProgressPercentage = (int)(dProgressPercentage * 100);

                if (backgroundWorker1.CancellationPending)
                {
                  e.Cancel = true;
                  streamLocal.Close();
                  streamRemote.Close();
                  return;
                }
                backgroundWorker1.ReportProgress(iProgressPercentage);
              }
              streamLocal.Close();
            }
            streamRemote.Close();
          }
        }
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.ToString());
      }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      string sFilePathToWriteFileTo = Path.Combine(downloadDir, downloadFilename);
      if (e.Cancelled)
      {
        if (File.Exists(sFilePathToWriteFileTo))
        {

        }
      }
      else
      {
        if (File.Exists(sFilePathToWriteFileTo))
        {
          if (MessageBox.Show("File download complete.Install now?", "Install now?", MessageBoxButtons.YesNo) == DialogResult.Yes)
          {
            try
            {
              System.Diagnostics.Process.Start(sFilePathToWriteFileTo);
            }
            catch (Exception ex)
            {
              MessageBox.Show(ex.Message);
            }
          }
        }
      }
      parent.DownloadingFinished(this);
      panelDefault.Visible = true;
    }

    private void buttonCancelDownload_Click(object sender, EventArgs e)
    {
      backgroundWorker1.CancelAsync();
    }

    private void buttonOpenPage_Click(object sender, EventArgs e)
    {
      OpenPage(pageUrl);
    }

    public void CheckInstallation()
    {
      //checks the installation of the software
      SetInstalled(false);

      if (!string.IsNullOrEmpty(checkFileExists))
      {
        //check if the directory or file exists in Program files, applocaldata etc.
        string installFolderOfVS2010 = Helpers.GetInstallationFolderOfVS2010();

        string userData = Path.Combine(installFolderOfVS2010, checkFileExists);
        if (File.Exists(userData))
        {
          SetInstalled(true);
          return;
        }
        if (Directory.Exists(userData))
        {
          SetInstalled(true);
          return;
        }

        string commonProgData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles), checkFileExists);
        if (File.Exists(commonProgData))
        {
          SetInstalled(true);
          return;
        }
        if (Directory.Exists(commonProgData))
        {
          SetInstalled(true);
          return;
        }

        string progData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), checkFileExists);
        if (File.Exists(progData))
        {
          SetInstalled(true);
          return;
        }
        if (Directory.Exists(progData))
        {
          SetInstalled(true);
          return;
        }

        string appLocalData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), checkFileExists);
        if (File.Exists(appLocalData))
        {
          SetInstalled(true);
          return;
        }
        if (Directory.Exists(appLocalData))
        {
          SetInstalled(true);
          return;
        }

      }
      else
      {
        if (regKey.Length > 0 && Registry.LocalMachine.OpenSubKey(regKey) != null)
        {
          SetInstalled(true);
          return;
        }
        //The registry key:
        string SoftwareKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
        using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(SoftwareKey))
        {
          //Let's go through the registry keys and get the info we need:
          foreach (string skName in rk.GetSubKeyNames())
          {
            using (RegistryKey sk = rk.OpenSubKey(skName))
            {
              try
              {
                //If the key has value, continue, if not, skip it:
                if (!(sk.GetValue("DisplayName") == null))
                {
                  if (sk.GetValue("DisplayName").ToString().StartsWith(productGuid))
                  {
                    SetInstalled(true);
                  }
                }
              }
              catch (Exception)
              {
              }
            }
          }
        }
      }
    }

    private void SetInstalled(bool installed)
    {
      this.isInstalled = installed;

      if (installed)
      {
        this.pictureBox1.Image = imageList1.Images[1];
      }
      else
      {
        this.pictureBox1.Image = imageList1.Images[0];
        if (!string.IsNullOrEmpty(this.downloadUrl))
        {
          //this.buttonDownload.Visible = false;
        }
      }
    }

    private void OpenPage(string url)
    {
      try
      {
        System.Diagnostics.Process.Start(url);
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message);
      }
    }

    internal void SetVSVersions(bool vs2008, bool vs2010)
    {
      this.Visible = false;
      if (string.IsNullOrEmpty(vsVersion))
      {
        this.Visible = true;
        return;
      }
      if (vs2008)
      {
        if (this.vsVersion == "2008")
        {
          this.Visible = true;
        }
      }
      if (vs2010)
      {
        if (this.vsVersion == "2010")
        {
          this.Visible = true;
        }
      }
    }

    private void button_install_Click(object sender, EventArgs e)
    {
      if (File.Exists(localExistingSetupFile))
      {
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = localExistingSetupFile;
        Process process = Process.Start(info);
      }
    }
  }
}
